package com.linkhub.oms.admin.modules.wms.service.impl;

import com.alibaba.fastjson.JSON;
import com.linkhub.oms.admin.modules.order.service.OrderBizService;
import com.linkhub.oms.admin.modules.user.accountflow.service.IUserAccountFlowBizService;
import com.linkhub.oms.admin.modules.wms.domain.dto.*;
import com.linkhub.oms.admin.modules.wms.domain.param.*;
import com.linkhub.oms.admin.modules.wms.domain.vo.WMSConfirmResponse;
import com.linkhub.oms.admin.common.enums.NeedCheckDuplicatedBiz;
import com.linkhub.oms.admin.modules.stock.service.StockHandler;
import com.linkhub.oms.admin.modules.wms.service.WmsConfirmService;
import com.linkhub.oms.admin.modules.wms.service.WmsDeliveryConfirmFulfillmentService;
import com.linkhub.oms.common.constant.WmsInfoConstant;
import com.linkhub.oms.common.enums.mp.*;
import com.linkhub.oms.common.util.QtBeanUtil;
import com.linkhub.oms.common.util.json.QtFastjsonUtil;
import com.linkhub.oms.dao.mpservice.IOrderService;
import com.linkhub.oms.dao.mpservice.IShopService;
import com.linkhub.oms.data.sync.api.wms.domain.request.WmsBaseURLRequest;
import com.linkhub.oms.data.sync.service.ShopifyDataSyncBizService;
import com.linkhub.oms.data.sync.util.SignUtil;
import com.linkhub.oms.entity.OrderEntity;
import com.linkhub.oms.entity.ShopEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;


import com.linkhub.oms.dao.mpservice.IDuplicatedRecordService;

/**
 * @author Jaycle
 * @version 1.0.0
 * @Description WMSConfirmServiceImpl.java
 * @createTime 2024/06/15 17:58
 */

@Slf4j
@Service
public class WmsConfirmServiceImpl implements WmsConfirmService {

    @Resource
    private IOrderService orderService;
    @Resource
    private OrderBizService orderBizService;
    @Resource
    private IShopService shopService;
    @Resource
    private ShopifyDataSyncBizService shopifyDataSyncBizService;
    @Resource
    private StockHandler stockHandler;
    @Resource
    private IDuplicatedRecordService duplicatedService;
    @Resource
    private WmsDeliveryConfirmFulfillmentService wmsDeliveryConfirmFulfillmentService;
    @Resource
    private IUserAccountFlowBizService userAccountFlowBizService;

    @Value("${wms.secretKey}")
    private String secretKey;

    @Override
    public WMSConfirmResponse wmsConfirms( WmsBaseURLRequest requestParam, String sign, String data ) {
        String wmsSign = SignUtil.createWmsSign(requestParam, secretKey, data);
        log.info(data);
//        if (!wmsSign.equals(sign)) {
//            log.info("签名验证不通过！OMS验证签名为：{}",wmsSign);
//
//            return WMSConfirmResponse.createFailureResult();
//        }
        String method = requestParam.getMethod();
        if (WmsInfoConstant.WMS_OPENAPI_ENTRYORDER_CONFIRM.equals(method)) {
            // 入库单确认
            WarehouseArrantConfirmParam warehouseArrantConfirmParam = QtFastjsonUtil.parse(data, WarehouseArrantConfirmParam.class);
            warehouseArrantConfirm(warehouseArrantConfirmParam);
        } else if (WmsInfoConstant.WMS_OPENAPI_STOCKOUT_CONFIRM.equals(method)) {
            // 出库单确认
            DeliveryListConfirmParam deliveryListConfirmParam = QtFastjsonUtil.parse(data, DeliveryListConfirmParam.class);
            deliveryListConfirm(deliveryListConfirmParam);
        } else if (WmsInfoConstant.WMS_OPENAPI_INVENTORY_REPORT.equals(method)) {
            // 库存盘点通知
            StockCountNoticeParam stockCountNoticeParam = QtFastjsonUtil.parse(data, StockCountNoticeParam.class);
            stockCountNotice(stockCountNoticeParam);
        } else if (WmsInfoConstant.WMS_OPENAPI_STOREPROCESS_CONFIRM.equals(method)) {
            // 加工单确认
            ProcessOrderNoticeParam processOrderNoticeParam = QtFastjsonUtil.parse(data, ProcessOrderNoticeParam.class);
            processOrderNotice(processOrderNoticeParam);
        } else if (WmsInfoConstant.WMS_OPENAPI_ADJUSTMENTORDER_CONFIRM.equals(method)) {
            // 转移单确认
            TransferOrderNoticeParam transferOrderNoticeParam = QtFastjsonUtil.parse(data, TransferOrderNoticeParam.class);
            transferOrderNotice(transferOrderNoticeParam);
        } else {
            return WMSConfirmResponse.createFailureResult();
        }

        return WMSConfirmResponse.createSuccessResult();
    }

    @Override
    public void warehouseArrantConfirm( WarehouseArrantConfirmParam warehouseArrantConfirmParam ) {
        WarehouseArrantConfirmDTO warehouseArrantConfirmDTO = transformWarehouseArrantConfirmDTO(warehouseArrantConfirmParam);
        boolean duplicated = duplicatedService.duplicated(NeedCheckDuplicatedBiz.WMS_INBOUND_CONFIRM.name(),
                warehouseArrantConfirmDTO.getOutBizCode(), warehouseArrantConfirmDTO);
        log.info("入库确认是否重复：{}", duplicated);
        if (!duplicated) {
            // 库存确认入库的逻辑调用
            stockHandler.wmsInboundConfirm(warehouseArrantConfirmDTO);
        }
    }

    public WarehouseArrantConfirmDTO transformWarehouseArrantConfirmDTO( WarehouseArrantConfirmParam warehouseArrantConfirmParam ) {
        WarehouseArrantConfirmDTO transformedEntryOrderDTO = new WarehouseArrantConfirmDTO();

        // 复制基础信息
        QtBeanUtil.copyProperties(warehouseArrantConfirmParam.getRequest().getEntryOrder(), transformedEntryOrderDTO);

        List<WarehouseArrantConfirmDTO.Product> products = new ArrayList<>();
        for (WarehouseArrantConfirmParam.OrderLine orderLine : warehouseArrantConfirmParam.getRequest().getOrderLines().getOrderLine()) {
            WarehouseArrantConfirmDTO.Product product = new WarehouseArrantConfirmDTO.Product();
            QtBeanUtil.copyProperties(orderLine, product);

            List<WarehouseArrantConfirmDTO.Product.Batch> batches = new ArrayList<>();
            for (WarehouseArrantConfirmParam.Batch batch : orderLine.getBatchs().getBatch()) {
                WarehouseArrantConfirmDTO.Product.Batch transformedBatch = new WarehouseArrantConfirmDTO.Product.Batch();
                QtBeanUtil.copyProperties(batch, transformedBatch);
                batches.add(transformedBatch);
            }
            product.setBatch(batches);
            products.add(product);
        }
        transformedEntryOrderDTO.setProduct(products);

        return transformedEntryOrderDTO;
    }

    @Override
    public WMSConfirmResponse deliveryListConfirm( DeliveryListConfirmParam deliveryListConfirmParam ) {
        DeliveryListConfirmDTO deliveryListConfirmDTO = transformDeliveryListConfirmDTO(deliveryListConfirmParam);
        String sysOrderId = deliveryListConfirmDTO.getDeliveryOrderCode();
        OrderEntity orderEntity = orderService.getByOrderId(sysOrderId);

        List<OrderEntity> orderEntityList = new ArrayList<>(Collections.singletonList(orderEntity));

        // 对比可推送订单是否有带更新数据
        boolean updateFlag = orderBizService.syncOrderIfNecessary(orderEntityList);

        if (updateFlag) {
            // 同步订单
            try {
                ShopEntity shopEntity = shopService.getByShopId(orderEntity.getSysShopId());
                shopifyDataSyncBizService.syncShopOrders(shopEntity);
            } catch (Exception e) {
                return WMSConfirmResponse.createFailureResult();
            }
        }
        // 获取订单最新数据
        orderEntity = orderService.getByOrderId(sysOrderId);
        // 如果订单不是待打包状态或者是已取消状态，则不确认出库
        if (!EmployeeBusinessStatusEnum.TO_BE_PACKAGED.equals(orderEntity.getEmployeeBusinessStatus())
                || OrderStatusEnum.CANCELLED.equals(orderEntity.getOrderStatus())) {
            return WMSConfirmResponse.createFailureResult();
        }

        // TODO：查询订单是否取消，没取消根据确认单信息决定是否处理此出库单，进行相应库存的操作，并更新订单状态为已发货
        System.out.println(JSON.toJSONString(deliveryListConfirmDTO));

        // TODO：仓库确认成功，需释放预占库存，扣减实物库存 @xieyu ；释放预占金额，扣减实际金额
        boolean duplicated = duplicatedService.duplicated(NeedCheckDuplicatedBiz.WMS_OUTBOUND_CONFIRM.name(),
                deliveryListConfirmDTO.getOutBizCode(), deliveryListConfirmDTO);
        log.info("出库确认是否重复：{}", duplicated);
        if (!duplicated) {
            // 库存确认出库的逻辑调用
            stockHandler.wmsOutboundConfirm(deliveryListConfirmDTO);
            // 重新计算运费，挂号费 -- 移除
            /*LogisticFreightVO logisticFreightVO =orderBizService.queryLogisticFreight(sysOrderId, orderEntity.getChannelCode());
            OrderLogisticParam logisticParam = new OrderLogisticParam();
            logisticParam.setChannelCode(orderEntity.getChannelCode());
            logisticParam.setEstimatedFreight(logisticFreightVO.getEstimatedFreight());
            logisticParam.setRegistrationFreight(logisticFreightVO.getRegistrationFreight());
            logisticParam.setSysOrderId(Lists.newArrayList(sysOrderId));
            orderBizService.updateOrderLogistic(logisticParam);

            BigDecimal estimatedFreight = Convert.toBigDecimal(logisticFreightVO.getEstimatedFreight(),BigDecimal.ZERO);
            BigDecimal registrationFreight = Convert.toBigDecimal(logisticFreightVO.getRegistrationFreight(),BigDecimal.ZERO);
            // 解冻，并支付,其中运费和挂号费支付最新计算的费用
            Map<ExpenseTypeEnum, BigDecimal> realPayMap = Maps.newHashMap();
            realPayMap.put(ExpenseTypeEnum.FREIGHT,estimatedFreight);
            realPayMap.put(ExpenseTypeEnum.REGISTRATION_FEE, registrationFreight);
            userAccountFlowBizService.unfreezeAccountFlowAndPayByDocumentId(sysOrderId, DocumentTypeEnum.ORDER,realPayMap);*/

        }

        // 出库单确认成功，更改订单状态
        OrderEntity update = new OrderEntity();
        update.setOrderStatus(OrderStatusEnum.DELIVERED);
        update.setCustomerBusinessStatus(CustomerBusinessStatusEnum.TRACKING);
        update.setEmployeeBusinessStatus(EmployeeBusinessStatusEnum.TRACKING);
        update.setEmployeeOrderStatus(EmployeeOrderStatusEnum.DELIVERED);
        update.setTrackBusinessStatus(TrackBusinessStatusEnum.NotFound);
        orderService.updateOrderInfo(sysOrderId, update);

        // 异步调用shopify api发货
        orderEntity = orderEntityList.get(0);   // orderEntityList经过deepMappingOrders填充才有shopInfo信息
        if (orderEntity.getShopInfo() != null && PlatFormEnum.SHOPIFY == orderEntity.getShopInfo().getPlatForm()) {
            wmsDeliveryConfirmFulfillmentService.runShopifyShipping(orderEntity);
        }

        return WMSConfirmResponse.createSuccessResult();
    }

    private DeliveryListConfirmDTO transformDeliveryListConfirmDTO( DeliveryListConfirmParam deliveryListConfirmParam ) {
        DeliveryListConfirmDTO dto = new DeliveryListConfirmDTO();

        DeliveryListConfirmParam.Request request = deliveryListConfirmParam.getRequest();
        if (request != null) {
            DeliveryListConfirmParam.DeliveryOrder deliveryOrder = request.getDeliveryOrder();
            if (deliveryOrder != null) {
                dto.setOutBizCode(deliveryOrder.getOutBizCode());
                dto.setDeliveryOrderCode(deliveryOrder.getDeliveryOrderCode());
                dto.setWarehouseCode(deliveryOrder.getWarehouseCode());
                dto.setOwnerCode(deliveryOrder.getOwnerCode());
            }

            ArrayList<DeliveryListConfirmDTO.OrderLineDTO> orderLineDTOS = new ArrayList<>();
            DeliveryListConfirmParam.OrderLines OriginOrderLines = request.getOrderLines();
            if (OriginOrderLines != null) {
                List<DeliveryListConfirmParam.OrderLine> orderLines = OriginOrderLines.getOrderLine();
                if (orderLines != null && !orderLines.isEmpty()) {
                    for (DeliveryListConfirmParam.OrderLine orderLine : orderLines) {
                        DeliveryListConfirmDTO.OrderLineDTO orderLineDTO = new DeliveryListConfirmDTO.OrderLineDTO();
                        orderLineDTO.setItemCode(orderLine.getItemCode());
                        orderLineDTO.setPlanQty(orderLine.getPlanQty());
                        orderLineDTOS.add(orderLineDTO);
                    }
                }
            }
            dto.setOrderLines(orderLineDTOS);

            ArrayList<DeliveryListConfirmDTO.ConsumableDetailDTO> consumableDetailDTOS = new ArrayList<>();
            DeliveryListConfirmParam.Packages OriginPackages = request.getPackages();
            if (OriginPackages != null) {
                List<DeliveryListConfirmParam.Package> packageList = OriginPackages.getPackageList();
                if (packageList != null && !packageList.isEmpty()) {
                    for (DeliveryListConfirmParam.Package pkg : packageList) {
                        DeliveryListConfirmParam.ConsumableDetails consumableDetails = pkg.getConsumableDetails();
                        if (consumableDetails != null) {
                            List<DeliveryListConfirmParam.ConsumableDetail> consumableDetailList = consumableDetails.getConsumableDetail();
                            if (consumableDetailList != null && !consumableDetailList.isEmpty()) {
                                for (DeliveryListConfirmParam.ConsumableDetail consumableDetail:consumableDetailList){
                                    DeliveryListConfirmDTO.ConsumableDetailDTO consumableDetailDTO = new DeliveryListConfirmDTO.ConsumableDetailDTO();
                                    consumableDetailDTO.setConsumableCode(consumableDetail.getConsumableCode());
                                    consumableDetailDTO.setQuantity(consumableDetail.getQuantity());
                                    consumableDetailDTOS.add(consumableDetailDTO);
                                }
                            }
                        }
                    }
                }
            }
            dto.setConsumableDetails(consumableDetailDTOS);
        }

        return dto;
    }

    @Override
    public void stockCountNotice( StockCountNoticeParam stockCountNoticeParam ) {
        StockCountNoticeDTO stockCountNoticeDTO = transformStockCountNoticeDTO(stockCountNoticeParam);

        boolean duplicated = duplicatedService.duplicated(NeedCheckDuplicatedBiz.WMS_STOCK_CHECK.name(),
                stockCountNoticeDTO.getOutBizCode(), stockCountNoticeDTO);
        log.info("盘点是否重复：{}", duplicated);
        if (!duplicated) {
            stockHandler.wmsStockCheck(stockCountNoticeDTO);
        }
    }

    private StockCountNoticeDTO transformStockCountNoticeDTO( StockCountNoticeParam stockCountNoticeParam ) {
        if (stockCountNoticeParam == null || stockCountNoticeParam.getRequest() == null) {
            return null;
        }

        StockCountNoticeDTO stockCountNoticeDTO = new StockCountNoticeDTO();
        StockCountNoticeParam.Request request = stockCountNoticeParam.getRequest();

        // Copy top-level properties
        QtBeanUtil.copyProperties(request, stockCountNoticeDTO);

        // Handle nested Items
        if (request.getItems() != null && request.getItems().getItem() != null) {
            List<StockCountNoticeDTO.Item> dtoItemsList = new ArrayList<>();
            for (StockCountNoticeParam.Item paramItem : request.getItems().getItem()) {
                StockCountNoticeDTO.Item dtoItem = new StockCountNoticeDTO.Item();
                QtBeanUtil.copyProperties(paramItem, dtoItem);
                dtoItemsList.add(dtoItem);
            }

            StockCountNoticeDTO.Items dtoItems = new StockCountNoticeDTO.Items();
            dtoItems.setItem(dtoItemsList);
            stockCountNoticeDTO.setItems(dtoItems);
        }

        return stockCountNoticeDTO;
    }

    @Override
    public void transferOrderNotice( TransferOrderNoticeParam transferOrderNoticeParam ) {
        TransferOrderNoticeDTO transferOrderNoticeDTO = transferOrderNoticeDTO(transferOrderNoticeParam);

        boolean duplicated = duplicatedService.duplicated(NeedCheckDuplicatedBiz.WMS_STOCK_TRANSFER.name(),
                transferOrderNoticeDTO.getOutBizCode(), transferOrderNoticeDTO);
        log.info("库存转移是否重复：{}", duplicated);
        if (!duplicated) {
            stockHandler.wmsStockTransfer(transferOrderNoticeDTO);
        }
    }

    private TransferOrderNoticeDTO transferOrderNoticeDTO( TransferOrderNoticeParam transferOrderNoticeParam ) {
        TransferOrderNoticeDTO dto = new TransferOrderNoticeDTO();

        TransferOrderNoticeParam.Request request = transferOrderNoticeParam.getRequest();
        if (request != null) {
            TransferOrderNoticeParam.AdjustmentOrder adjustmentOrder = request.getAdjustmentOrder();
            if (adjustmentOrder != null) {
                // Copy properties from adjustmentOrder to dto
                QtBeanUtil.copyProperties(adjustmentOrder, dto);
            }

            List<TransferOrderNoticeParam.OrderLine> orderLineList = request.getOrderLines().getOrderLine();
            if (orderLineList != null && !orderLineList.isEmpty()) {
                // Create a list to hold the items
                List<TransferOrderNoticeDTO.OrderLine> dtoOrderLines = new ArrayList<>();
                for (TransferOrderNoticeParam.OrderLine orderLine : orderLineList) {
                    TransferOrderNoticeDTO.OrderLine dtoOrderLine = new TransferOrderNoticeDTO.OrderLine();
                    // Copy properties from item to dtoItem
                    QtBeanUtil.copyProperties(orderLine, dtoOrderLine);

                    TransferOrderNoticeDTO.OrderLine.Source dtoSource = new TransferOrderNoticeDTO.OrderLine.Source();
                    if (orderLine.getSource() != null) {
                        // Copy properties from item.getSource() to dtoSource
                        QtBeanUtil.copyProperties(orderLine.getSource(), dtoSource);
                    }
                    dtoOrderLine.setSource(dtoSource);

                    TransferOrderNoticeDTO.OrderLine.Target dtoTarget = new TransferOrderNoticeDTO.OrderLine.Target();
                    if (orderLine.getTarget() != null) {
                        // Copy properties from item.getTarget() to dtoTarget
                        QtBeanUtil.copyProperties(orderLine.getTarget(), dtoTarget);
                    }
                    dtoOrderLine.setTarget(dtoTarget);

                    // Add the dtoItem to the dtoItems list
                    dtoOrderLines.add(dtoOrderLine);
                }
                // Set the items in the dto
                dto.setOrderLines(dtoOrderLines);
            }
        }

        return dto;
    }

    @Override
    public void processOrderNotice( ProcessOrderNoticeParam processOrderNoticeParam ) {
        log.info("加工单确认报文：{}",processOrderNoticeParam);
        ProcessOrderNoticeDTO processOrderNoticeDTO = transferProcessOrderNoticeDTO(processOrderNoticeParam);
        // TODO：根据确认单信息决定是否处理此出库单，进行相应库存的操作，注意要根据outBizCode判断是否重复请求
        boolean duplicated = duplicatedService.duplicated(NeedCheckDuplicatedBiz.WMS_COMBINE_PROCESSING_CONFIRM.name(),
                processOrderNoticeDTO.getOutBizCode(), processOrderNoticeDTO);
        log.info("组合加工确认是否重复：{}", duplicated);
        if (!duplicated) {
            // 库存确认出库的逻辑调用
            stockHandler.wmsCombineProcessingConfirm(processOrderNoticeDTO);
            // 解冻并支付加工费
            userAccountFlowBizService.unfreezeAccountFlowAndPayByDocumentId(processOrderNoticeDTO.getProcessOrderCode(),DocumentTypeEnum.PROCESS_ORDER);

        }

        System.out.println(JSON.toJSONString(processOrderNoticeDTO));
    }

    private ProcessOrderNoticeDTO transferProcessOrderNoticeDTO( ProcessOrderNoticeParam processOrderNoticeParam ) {
        ProcessOrderNoticeDTO processOrderNoticeDTO = new ProcessOrderNoticeDTO();

        // 复制基本字段
        QtBeanUtil.copyProperties(processOrderNoticeParam.getRequest(), processOrderNoticeDTO);

        // 复制MaterialItems
        ProcessOrderNoticeParam.MaterialItems materialItems = processOrderNoticeParam.getRequest().getMaterialitems();
        if (materialItems != null) {
            List<ProcessOrderNoticeDTO.MaterialItem> materialItemList = materialItems.getItem().stream().map(paramItem -> {
                ProcessOrderNoticeDTO.MaterialItem materialItem = new ProcessOrderNoticeDTO.MaterialItem();
                QtBeanUtil.copyProperties(paramItem, materialItem);
                return materialItem;
            }).collect(Collectors.toList());
            processOrderNoticeDTO.setMaterialitems(materialItemList);
        }

        // 复制ProductItems
        final ProcessOrderNoticeParam.ProductItems productitems = processOrderNoticeParam.getRequest().getProductitems();
        if (productitems != null) {
            List<ProcessOrderNoticeDTO.ProductItem> productItemList = productitems.getItem().stream().map(paramItem -> {
                ProcessOrderNoticeDTO.ProductItem productItem = new ProcessOrderNoticeDTO.ProductItem();
                QtBeanUtil.copyProperties(paramItem, productItem);
                return productItem;
            }).collect(Collectors.toList());
            processOrderNoticeDTO.setProductitems(productItemList);
        }
        return processOrderNoticeDTO;
    }
}
